#! /usr/bin/python
# -*- coding:  utf-8 -*-
#
# accoufer : cgi script for responding to an offer
# 
# Copyright S.Keim 2011
# Available under the MIT licence see the COPYING file


import accoufer
import shelve
import cgi 
import urllib2, urllib, math

def run():
    class param:
        svalue = 0
    
    # logged user
    login, user = accoufer.userCookie()
        
    # mendatory parameters
    form = cgi.FieldStorage()
    try:
        param.sref = form["sref"].value
        param.oref = form["oref"].value
        param.tx = float(form["tx"].value)
    except KeyError, ValueError:
        return fatal_error("Invalid parameters")
        
    offers = shelve.open(accoufer.offerpath(param.sref), 'r')
    param.url = offers[accoufer.URL_KEY]
    
    # other parameters
    if "svalue" not in form:
        print accoufer.HTML%( "Response", FORM%param.__dict__)
        return 
    try:
        param.svalue = int(form["svalue"].value)
    except KeyError, ValueError:
        return error(param, "Invalid value")
        
    # get information about offer from server
    data = urllib.urlencode({"client":accoufer.SERVICE_URL, "oref":param.oref})
    try:
        f = accoufer.urlopen(param.url+"/offers", data=data)     
    except IOError:
        return error(param,  "Unable to contact server") 
    if f.next() != "OK\n":
        code = f.next()
        return error(param,  f.next())
    row = f.next().strip()
    if not row:
        return fatal_error("Offer removed from server")
    oref, o_svalue, min_svalue, tx, i_email = row.split(',')
    
    tx = float(tx)
    if abs(param.tx - tx)> 0.00001:
        return fatal_error("Offer conditions changed on server")

    emails = shelve.open(accoufer.EMAIL_PATH)      
    try:
        i_login = emails[i_email.strip()]
    except KeyError:
        return fatal_error("Unknown initer")
        
    users = shelve.open(accoufer.USER_PATH)
    initer = users[i_login]   
    # check input
    if  param.svalue<int(min_svalue):
        return error(param, "Value must be greater than "+min_svalue)
    if param.svalue>int(o_svalue):
        return error(param, "Value must be lower than "+o_svalue)
    cvalue = int(math.ceil(tx*param.svalue))
    if user[accoufer.USER_CREDITS]<cvalue:
        return error(param, "Credits overflow")
        
    #connect to server
    data = urllib.urlencode({"client":accoufer.SERVICE_URL, "oref":param.oref,
        "svalue":param.svalue, "cvalue":cvalue, "responder":user[accoufer.USER_EMAIL]})
    try:
        g = accoufer.urlopen(param.url+"/response", data=data)
    except IOError:
        return error(param, "Unable to contact server") 
    if g.next() != "OK\n":
        code = g.next()
        msg = g.next()
        return error(param, "Server error: "+msg)
    
    # do transaction
    rmail, rpwd, rcredit, roffers = user
    rcredit -= cvalue
    users[login] = rmail, rpwd, rcredit, roffers 
    
    imail, ipwd, icredit, ioffers  = initer
    icredit += cvalue
    users[i_login] = imail, ipwd, icredit, ioffers
    
    # log transaction
    accoufer.log(login, "Y", param.url, param.svalue, -cvalue, rcredit)
    accoufer.log(i_login, "N", param.url, -param.svalue, cvalue, rcredit)
    
    
    print accoufer.HTML%( "Response success", SUCCES )    
    
def error(param, txt):
    param.err = txt
    msg = ERROR%param.__dict__
    print accoufer.HTML%("Error", msg)

def fatal_error(txt):
    print accoufer.HTML%("Fatal error", "<h1>Error</h1>%s"%txt)
    
IN_FORM = """<form method=post action="./xrespond">
Do transfer for <input name="svalue" value="%(svalue)s"> credit on remote service<br/>
<input type="hidden" name="tx" value="%(tx)s"/>
<input type="hidden" name="oref" value="%(oref)s"/>
<input type="hidden" name="sref" value="%(sref)s"/>
<input type="submit" value="Run"/></form><p/>

"""
FORM = "<h1>Respond</h1>"+IN_FORM

ERROR = "<h1>Respond</h1><b>%(err)s</b><p/>"+IN_FORM

SUCCES = """<h1>Response</h1>Response success"<p/> <a href="./index.html">Start</a>"""

if __name__=="__main__":
    run()
